ICTSC2019 二次予選 問題解説: 君k8s得意って言っていたよね?

問題文

職場でkubernetesを用いてRedmineを導入することになった。
上司が構築作業をしていたが、どうもうまくRedmineが起動しないらしい。

部下のあなたがk8sが得意ということだったので、構築作業の続きをすることになった。
kubernetesが動作するサーバーにRedmine用のManifestが適用されているが、どうも正常起動していないようだ。

原因を究明を行い、Redmineを使える状態にして解決方法を報告してください。

問題のゴール

  • VNCクライアントのブラウザからRedmineが閲覧できること。
    http://192.168.0.100:30000
  • Redmineのデータがコンテナ再起動時にも保持されていること。

情報

  • Server:
  • k8smaster1:
    • ip: 192.168.0.100
    • userid: root
    • password: USerPw@19
  • container-registry:
    • ip: 192.168.0.101
    • 備考: 操作不可
  • Redmine_Manifest:
    • path: “/root/ictsc_problem_manifests/*.yaml”
  • Redmineログイン情報
    • userid: ictsc
    • password: USerPw@19

制限事項

  • Redmineは指定のManifest(Redmine_Manifest)でデプロイしてください。
  • Redmine_Manifestは変更出来ません。
  • Redmine_Manifest内のコンテナイメージはcontainer-registryから取得してください。
  • マニフェストの再適用, OSの再起動の操作は可能です。
  • 誤操作等で競技続行不可の場合は出題時環境への復元のみ承ります。

Kubernetes上にRedmineサービスを稼働させる問題です。
出題時にはRedmineを構成するRedmine-Pod, MariaDB-PodがPendingとなっており、利用不可の状態です。
コンテナが稼働しない原因を突き止め対処することでRedmineサービスを稼働させることができます。

問題解決のために以下の原因を解決する必要があります。

  1. masterへpodのデプロイに関するtaintsの削除
  2. コンテナランタイムcri-oにinsecure-registryの設定を追加
  3. MariaDBのPersistentVolumeのディレクトリ権限(Permission)を修正

問題解説

Kubernetes上にRedmineサービスを稼働させる問題です。
出題時にはRedmineを構成するRedmine-Pod, MariaDB-PodがPendingとなっており、利用不可の状態です。
コンテナが稼働しない原因を突き止め対処することでRedmineサービスを稼働させることができます。

masterへpodのデプロイに関するtaintsの削除

kubectl get podでコンテナの状態を見ます。

[root@k8smaster1 ~]# kubectl get pod
NAME                                  READY   STATUS    RESTARTS   AGE
my-release-mariadb-0                  0/1     Pending   0          9d
my-release-redmine-859cf77958-n95j5   0/1     Pending   0          9d

redmineとmariadbがpendingになっています。
kubectl describe pod <pod名> で各Podの状態を確認すると以下のイベントが確認できます。

Events:
  Type     Reason            Age                 From               Message
  ----     ------            ----                ----               -------
  Warning  FailedScheduling  9d (x5 over 9d)     default-scheduler  0/1 nodes are available: 1 node(s) had taints that the pod didn't tolerate.

nodeのtaintsをpodが許容できないということなので、nodeのtaintskubectl describe nodesで確認します。

[root@k8smaster1 ~]# kubectl describe nodes
Name:               k8smaster1
Roles:              master
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=k8smaster1
                    kubernetes.io/os=linux
                    node-role.kubernetes.io/master=
Annotations:        kubeadm.alpha.kubernetes.io/cri-socket: /var/run/crio/crio.sock
                    node.alpha.kubernetes.io/ttl: 0
                    volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Sat, 23 Nov 2019 19:58:55 +0900
Taints:             node-role.kubernetes.io/master:NoSchedule

Taintsがnode-role.kubernetes.io/master:NoScheduleのため、Labelsにmasterが指定されているこのノードにはPodをScheduleすることができません。
今回はシングルノードのMasterノードでデプロイさせたいので、このtaintsを削除します。

[root@k8smaster1 ~]# kubectl taint nodes k8smaster1 node-role.kubernetes.io/master:NoSchedule-
node/k8smaster1 untainted

これでPodがノードにScheduleされるようになりました。

コンテナランタイムcri-oにinsecure-registryの設定を追加

再度kubectl get podで確認すると以下となりImagePullBackOffとなっています。

[root@k8smaster1 ~]# kubectl get pod
NAME                                  READY   STATUS             RESTARTS   AGE
my-release-mariadb-0                  0/1     ImagePullBackOff   0          9d
my-release-redmine-859cf77958-n95j5   0/1     ImagePullBackOff   0          9d

kubectl desctibe pod <Pod名>でEventを確認すると以下のエラーが確認できます。

Failed to pull image "private-registry.local/bitnami/mariadb:10.3.20-debian-9-r0": rpc error: code = Unknown desc = pinging docker registry returned: Get https://private-registry.local/v2/: dial tcp 192.168.0.101:443: connect: no route to host

コンテナイメージのpullの際に192.168.0.101:443への接続ができていません。
情報で示されているように192.168.0.101はContainer-Registryです。

/etc/hosts192.168.0.101 private-registry.localの記載があり、正しいことがわかります。

試しにDockerでImageのpullに失敗したコンテナイメージを手動でdocker pull private-registry.local/bitnami/mariadb:10.3.20-debian-9-r0してみます。
この操作は正常にpullすることができ、docker imagesでも正しくコンテナイメージがあることが確認できました。

[root@k8smaster1 ~]# docker images
REPOSITORY                               TAG                   IMAGE ID            CREATED             SIZE
private-registry.local/bitnami/mariadb   10.3.20-debian-9-r0   36300b3aaaa0        3 weeks ago         289 MB

ここで再度k8s上のPodの状態を確認しますが、エラーに変化はありません。

[root@k8smaster1 ~]# kubectl get pod
NAME                                  READY   STATUS             RESTARTS   AGE
my-release-mariadb-0                  0/1     ImagePullBackOff   0          9d
my-release-redmine-859cf77958-n95j5   0/1     ImagePullBackOff   0          9d

さらに詳細にみるために全namespaceを対象にget podします。

[root@k8smaster1 ~]# kubectl get pod --all-namespaces
NAMESPACE     NAME                                  READY   STATUS             RESTARTS   AGE
default       my-release-mariadb-0                  0/1     ImagePullBackOff   0          9d
default       my-release-redmine-859cf77958-n95j5   0/1     ImagePullBackOff   0          9d
kube-system   coredns-74c9d4d795-hj9tn              1/1     Running            3          9d
kube-system   coredns-74c9d4d795-l7949              0/1     Pending            0          9d
kube-system   dns-autoscaler-7d95989447-crv67       1/1     Running            3          9d
kube-system   kube-apiserver-k8smaster1             1/1     Running            3          9d
kube-system   kube-controller-manager-k8smaster1    1/1     Running            3          9d
kube-system   kube-proxy-mm8ld                      1/1     Running            3          9d
kube-system   kube-scheduler-k8smaster1             1/1     Running            3          9d
kube-system   nodelocaldns-wgq47                    1/1     Running            3          9d
kube-system   weave-net-z97jl                       2/2     Running            6          9d

RunningのPodがあるのに、docker imagesでは手動でpullしたイメージしかありませんでした。

何かおかしいですね。Dockerが使われていないのかもしれません。

k8sのコンテナランライムを確認するためにkubeletのユニットファイルを確認します。
ファイル/etc/systemd/system/kubelet.serviceに記載の環境変数ファイル/etc/kubernetes/kubelet.envには以下の記載があります。

KUBELET_ARGS="--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf \
--config=/etc/kubernetes/kubelet-config.yaml \
--kubeconfig=/etc/kubernetes/kubelet.conf \
--pod-infra-container-image=gcr.io/google_containers/pause-amd64:3.1 \
--container-runtime=remote \
--container-runtime-endpoint=/var/run/crio/crio.sock \
--runtime-cgroups=/systemd/system.slice \
 --node-labels=  "

container-runtimecrioが指定されていることがわかります。
しっかりとサービスが動いていますね。

[root@k8smaster1 ~]# systemctl status crio
● crio.service - Open Container Initiative Daemon
   Loaded: loaded (/usr/lib/systemd/system/crio.service; enabled; vendor preset: disabled)
   Active: active (running) since Tue 2019-12-03 00:39:10 JST; 49min ago
     Docs: https://github.com/kubernetes-sigs/cri-o
 Main PID: 1076 (crio)
   CGroup: /system.slice/crio.service
           └─1076 /usr/bin/crio

crioはCRIなのでcrictlによる操作が可能です。
crictl imagesの結果ではrunningだったPodのコンテナイメージがありました。

[root@k8smaster1 ~]# crictl images
IMAGE                                              TAG                 IMAGE ID            SIZE
docker.io/coredns/coredns                          1.6.0               680bc53e5985f       42.3MB
docker.io/weaveworks/weave-kube                    2.4.0               86ff1a48ce14d       134MB
docker.io/weaveworks/weave-npc                     2.4.0               647ad6d59818d       49.5MB
gcr.io/google-containers/kube-apiserver            v1.15.3             5eb2d3fc7a44e       208MB
gcr.io/google-containers/kube-controller-manager   v1.15.3             e77c31de55475       160MB
gcr.io/google-containers/kube-proxy                v1.15.3             232b5c7931462       84.3MB
gcr.io/google-containers/kube-scheduler            v1.15.3             703f9c69a5d57       82.7MB
k8s.gcr.io/cluster-proportional-autoscaler-amd64   1.6.0               dfe4432cd2e2b       48.9MB
k8s.gcr.io/k8s-dns-node-cache                      1.15.4              3f8330c31e7d5       64.3MB
k8s.gcr.io/pause                                   3.1                 da86e6ba6ca19       747kB
gcr.io/google-containers/pause                     3.1                 da86e6ba6ca19       747kB

k8sのコンテナランタイムとしてcri-oが動作していたので、80ポートでアクセスさせるために、cri-oのprivate-resigtryへのinsecure-registryを追加しましょう。

214  # insecure_registries is used to skip TLS verification when pulling images.
215  insecure_registries = [
216    "10.233.0.0/24",
217    "private-registry.local"
218  ]

MariaDBのPersistentVolumeのディレクトリ権限(Permission)を修正

crioの設定を反映させた後、再度k8sのpodを確認します。

[root@k8smaster1 ~]# kubectl get pod
NAME                                  READY   STATUS    RESTARTS   AGE
my-release-mariadb-0                  0/1     Error     5          9d
my-release-redmine-859cf77958-n95j5   0/1     Running   1          9d

mariadbがエラーになっています。
コンテナの立ち上げは行われているので、コンテナのlogを確認します。

[root@k8smaster1 ~]# kubectl logs  my-release-mariadb-0
 16:43:21.98
 16:43:21.98 Welcome to the Bitnami mariadb container
 16:43:21.98 Subscribe to project updates by watching https://github.com/bitnami/bitnami-docker-mariadb
 16:43:21.98 Submit issues and feature requests at https://github.com/bitnami/bitnami-docker-mariadb/issues
 16:43:21.98 Send us your feedback at [email protected]
 16:43:21.99
 16:43:21.99 INFO  ==> ** Starting MariaDB setup **
 16:43:22.04 INFO  ==> Validating settings in MYSQL_*/MARIADB_* env vars
 16:43:22.04 INFO  ==> Initializing mariadb database
mkdir: cannot create directory '/bitnami/mariadb/data': Permission denied

'/bitnami/mariadb/data': Permission denied ディレクトリの権限不足のようですね。

/root/ictsc_problem_manifestsにあるk8sManifestを読み解くと、/var/opt/pv{1,2}にPersistentVolumeがあることがわかります。
kubectl get pvの結果よりmariaDBに対応するPathにchmod で権限を付与します。

[root@k8smaster1 ictsc_problem_manifests]# kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                               STORAGECLASS   REASON   AGE
pv0001   20Gi       RWO            Recycle          Bound    default/data-my-release-mariadb-0                           9d
pv0002   20Gi       RWO            Recycle          Bound    default/my-release-redmine                                  9d

[root@k8smaster1 ]# chmod -R 777 /var/opt/pv1/

再度k8sのPodの状況を確認すると正常にRedmineのPodが稼働していることが確認できました。

[root@k8smaster1 opt]# kubectl get pod
NAME                                  READY   STATUS             RESTARTS   AGE
my-release-mariadb-0                  1/1     Running            9          9d
my-release-redmine-859cf77958-n95j5   1/1     Running            5          9d

VNCのブラウザからRedmineのページが閲覧できれば完了です。